package workflow.dto;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import common.ObjectUtil;

import workflow.WorkflowUtil;
import workflow.core.WorkflowBlock;
import workflow.core.WorkflowElement;

public class WorkflowProcessDefinition {
	
	/** lista zawierajaca informacje o polaczeniach miedzy blokami */
	private List<WorkflowConnection> connections;
	
	/** mapa z blokami uzytymi w procesie */
	private List<WorkflowBlock> workflowBlocks;
	
	/** mapa z parametrami dla poszczegolnych elementow.
	 * klucz to nazwa_bloku:nazwa_elementu */
	private Map<String, Map<String, String>> elementsParameters;
	
	public WorkflowProcessDefinition() {
		this.elementsParameters = new HashMap<String, Map<String,String>>();
		this.workflowBlocks = new ArrayList<WorkflowBlock>();
		this.connections = new ArrayList<WorkflowConnection>();
	}
	
	/** setuje parametry z mapy wszystkim elementom procesu */
	public void initizalizeElementsParameters(){
		Iterator<WorkflowBlock> it = this.getWorkflowBlocks().iterator();
	    while (it.hasNext()) {
	    	WorkflowBlock block = it.next();
	    	for(WorkflowElement element : block.getElements()){
	    		String paramsKey = block.getName()+":"+element.getName();
	    		Map<String,String> params = this.getElementParameters(paramsKey);
	    		element.setParams(params);
	    	}
	    }
	}

	public List<WorkflowBlock> getWorkflowBlocks() {
		return workflowBlocks;
	}
	
	public Map<String, String> getElementParameters(String key) {
		return elementsParameters.get(key);
	}
	
	public WorkflowBlock getWorkflowBlockByName(String blockName){
		for(WorkflowBlock block: workflowBlocks){
			if(block.getName().equals(blockName)){
				return block;
			}
		}
		return null;
	}
	
	public WorkflowConnection getConnectionBySource(String source){
		for(WorkflowConnection conn: connections){
			if(conn.getSource().equals(source)){
				return conn;
			}
		}
		return null;
	}

	public void setConnections(List<WorkflowConnection> connections) {
		this.connections = connections;
	}

	public void setWorkflowBlocks(List<WorkflowBlock> blocks) {
		this.workflowBlocks = blocks;
	}

	public void setElementsParameters(Map<String, Map<String, String>> elementsParams) {
		this.elementsParameters = elementsParams;
	}

	/** zwraca kopie definicji procesu */
	public WorkflowProcessDefinition getCopy() {
		WorkflowProcessDefinition def = new WorkflowProcessDefinition();
		
		// kopiuje polaczenia
		List<WorkflowConnection> conns = new ArrayList<WorkflowConnection>();
		for(WorkflowConnection conn : this.connections){
			conns.add(conn.getCopy());
		}
		
		// kopiuje mape z parametrami
		Map<String, Map<String, String>> elementsParams = new HashMap<String, Map<String,String>>();
		for (Map.Entry<String, Map<String, String>> entry : this.elementsParameters.entrySet()){
			String key = entry.getKey();
			Map<String, String> map = new HashMap<String, String>(entry.getValue());
			elementsParams.put(key, map);
		}
		
		// kopiuje WorkflowBlocki - uzywam serializacji poniewaz 
		// dzieki temu nie bede musial implementowac getCopy w kazdej pochodnej
		List<WorkflowBlock> blocks = new ArrayList<WorkflowBlock>();
		for(WorkflowBlock block : this.workflowBlocks){
			WorkflowBlock newBlock = (WorkflowBlock)ObjectUtil.getCopy((Object)block);
			blocks.add(newBlock);
		}

		// ustawiam skopiowane elementy
		def.setConnections(conns);
		def.setElementsParameters(elementsParams);
		def.setWorkflowBlocks(blocks);
		
		return def;
	}
}
